package util.approx;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * Declare the class to be an approximation of some other.<br>
 * It is mandatory to mark class as {@link Approx} and provide explicit list of classes that are supported to be mapping source.<br>
 * Annotate members to change default mapping by name.<br>
 * <p>
 * Don't be addicted to mappings. There are really few cases where mapping is reasonable.
 * <ul>
 * <li>Map objects from remote domain (possibly generated one) to your own domain objects.</li>
 * <li>Create lightweight approximation of your huge business objects to send to client in client - server application.</li>
 * </ul>
 * 
 * @see Modifier
 * @author Mykhaylo Adamovych
 */
@Retention(RetentionPolicy.RUNTIME)
public @interface Approx {
    
    /**
     * In case of class annotation - list of classes suitable to be mapped from.<br>
     * In case of member annotation - list of classes explicitly overridden.<br>
     * Both short and extended names fit.<br>
     * String names were used intentionally, not to require remote classes in classpath.
     */
    String[] source() default {};
    
    /**
     * Field path to map value from. By default destination object field name is used as a path for mapping.
     * <p>
     * Here is contract between {@link #path()} and {@link #source()}:
     * <ul>
     * <li>Elements order in one array correspond to elements order in another.</li>
     * <li>Path array could have one more tail element (correspond to null class) which will override default mapping by filed name.</li>
     * </ul>
     * 
     * <pre>
     * someFieldWithDifferentName
     * someInnerObject.getSomeValue()
     * ; - skip evaluation
     * </pre>
     */
    String[] path() default {};
    
    /**
     * Provide class of the item in the collection to perform deep mapping. Otherwise generic info will be lost at runtime and mapping of each item in the
     * collection impossible.
     * 
     * @see Mapper#resolve(Object)
     * @see OneToMany#targetEntity()
     */
    Class<? extends Object> targetEntity() default Object.class;
    
    /**
     * If false exception will be thrown in case of evaluated null value.<br>
     * True by default.
     */
    boolean nullable() default true;
    
    /**
     * List of modificators.
     * 
     * @see Modifier
     */
    Modifier[] mode() default {};
}
